<template>
    <el-scrollbar v-if="tabActive" ref="scrollbarRef" class="relative">
        <div ref="innerRef" class="m-5 p-4 rounded-xl bg-page">
            <div class="font-bold text-lg text-tx-regular">全文翻译</div>
            <div>
                <div v-if="nextStep >= 1" class="flex items-center mt-4 text-tx-secondary">
                    <icon
                        :name="nextStep === 1 ? 'el-icon-Refresh' : 'el-icon-Tickets'"
                        :class="nextStep === 1 ? 'is-loading' : ''"
                        :color="nextStep === 1 ? 'var(--el-color-primary)' : ''"
                    />
                    <span v-if="nextStep !== 1" class="ml-2">文档提取完成</span>
                    <span v-else class="ml-2 text-primary">正在提取文档</span>
                </div>
                <div v-if="nextStep >= 2" class="flex items-center mt-4 text-tx-secondary">
                    <icon
                        :name="nextStep === 2 ? 'el-icon-Refresh' : 'el-icon-DocumentChecked'"
                        :class="nextStep === 2 ? 'is-loading' : ''"
                        :color="nextStep === 2 ? 'var(--el-color-primary)' : ''"
                    />
                    <span v-if="nextStep !== 2" class="ml-2">文档总结完毕</span>
                    <span v-else class="ml-2 text-primary">AI分析总结中</span>
                </div>
            </div>
            <div v-if="content.length" class="mt-4 w-full overflow-auto">
                <Markdown :content="content" />
                <div v-if="!isReceiving" class="mt-5">
                    <el-button link @click="resetChats">
                        <template #icon>
                            <Icon name="el-icon-RefreshLeft" />
                        </template>
                        重新生成
                    </el-button>
                    <el-button link @click="handleCopy">
                        <template #icon>
                            <Icon name="el-icon-CopyDocument" />
                        </template>
                        复制
                    </el-button>
                </div>
            </div>
        </div>

        <el-button
            v-if="isReceiving"
            type="primary"
            class="absolute bottom-2 left-[43%]"
            @click="streamReader?.cancel()"
        >
            <icon name="el-icon-Refresh" class="is-loading" />
            <span>停止输出</span>
        </el-button>
    </el-scrollbar>

    <div v-else v-loading="firstLoading" class="flex flex-col items-center justify-center h-full">
        <el-empty v-if="!firstLoading && !translate" description="选择您要翻译的语言开始翻译吧">
            <div class="mb-8 mt-4">
                <el-radio-group v-model="language">
                    <el-radio-button label="中文" value="简体中文" />
                    <el-radio-button label="英文" value="英文" />
                    <el-radio-button label="日文" value="日文" />
                    <el-radio-button label="德文" value="德文" />
                </el-radio-group>
            </div>
            <el-button
                type="primary"
                round
                :loading="isReceiving"
                @click="sendChats"
            >
                <template #icon>
                    <icon name="el-icon-Refresh" size="18" />
                </template>
                开始翻译
            </el-button>
        </el-empty>
    </div>
</template>

<script setup lang="ts">
import { ElScrollbar } from 'element-plus'
import { useElementSize, watchThrottled, useClipboard } from '@vueuse/core'
import useUserStore from '~/stores/user'
import toolsUtil from '~/utils/tools'
import docsFilesApi from '~/api/apply/docs/files'

const props = defineProps({
    // 文件编号
    fileCode: {
        type: String,
        default: ''
    },
    // 翻译内容
    translate: {
        type: String,
        default: ''
    }
})

const userStore = useUserStore()
const { copy } = useClipboard()

// 首次加载
const firstLoading = ref<boolean>(true)

// 窗口节点
const innerRef = ref<HTMLDivElement>()
const scrollbarRef = shallowRef<InstanceType<typeof ElScrollbar>>()

// 对话数据
const content = ref<string>('')
const nextStep = ref<number>(1)
const tabActive = ref<boolean>(false)
const isReceiving = ref<boolean>(false)
let streamReader: ReadableStreamDefaultReader<Uint8Array> | null = null

// 翻译语言
const language = ref<string>('简体中文')

/**
 * 复制内容
 */
const handleCopy = async () => {
    try {
        await copy(content.value)
        feedback.msgSuccess('复制成功')
    } catch {
        feedback.msgSuccess('复制失败')
    }
}

/**
 * 重新翻译
 */
const resetChats = async () => {
    feedback.confirm('您确定要重新翻译吗？可能会产生额外的费用~')
        .then(async () => {
            await sendChats()
        })
}

/**
 * 发起对话
 */
const sendChats = async () => {
    content.value = ''
    nextStep.value = 1
    tabActive.value = true
    await toolsUtil.delay(2000)

    nextStep.value = 2
    isReceiving.value = true
    try {
        await docsFilesApi.sendChat({
            type: 'translate',
            code: props.fileCode,
            question: language.value
        }, {
            onstart(reader) {
                streamReader = reader
            },
            onmessage(value) {
                value.trim().split('data:').forEach(async (text) => {
                    if (text !== '' && text !== '[DONE]') {
                        try {
                            const dataJson = JSON.parse(text)
                            if (dataJson.error) {
                                content.value = dataJson.error.message
                                return feedback.msgError(dataJson.error.message)
                            }

                            const { choices } = dataJson
                            const data  = choices[0]?.delta.content
                            content.value += data
                        } catch { /* empty */ }
                    }
                })
            },
            async onclose() {
                nextStep.value = 3
                isReceiving.value = false
                await userStore.getUser()
            }
        })
    } catch (e: any) {
        nextStep.value = 3
        isReceiving.value = false
        content.value = e.message
        streamReader?.cancel()
    }
}

/**
 * 滚动条到底部
 */
const scrollToBottom = () => {
    const scrollHeight: number | any = scrollbarRef.value?.wrapRef?.scrollHeight
    const clientHeight: number | any = scrollbarRef.value?.wrapRef?.clientHeight
    const scrollH = scrollHeight - clientHeight
    scrollbarRef.value?.setScrollTop(scrollH)
}

/**
 * 监听高度变化
 */
const { height } = useElementSize(innerRef)
watchThrottled(
    height,
    () => {
        if (isReceiving.value) {
            scrollToBottom()
        }
    },
    { throttle: 500, immediate: true }
)

/**
 * 监听翻译变化
 */
watchThrottled(
    () => props.translate,
    async () => {
        const texts = props.translate || ''
        if (texts) {
            nextStep.value = 3
            content.value = texts
            tabActive.value = true
        } else {
            nextStep.value = 1
            tabActive.value = false
            firstLoading.value = false
        }

        await toolsUtil.delay(500)
        firstLoading.value = false
    },
    { throttle: 500, immediate: true }
)
</script>
